import 'package:file/memory.dart';
import 'package:patrol_cli/src/pubspec_reader.dart';
import 'package:test/test.dart';

void main() {
  late PubspecReader reader;
  late MemoryFileSystem fs;

  setUp(() {
    fs = MemoryFileSystem();
    final projectRoot = fs.directory('/project')..createSync();
    reader = PubspecReader(projectRoot: projectRoot);
  });

  group('getPatrolVersion', () {
    test('returns null when pubspec.lock does not exist', () {
      expect(reader.getPatrolVersion(), isNull);
    });

    test('returns null when packages section is missing', () {
      fs.file('/project/pubspec.lock').writeAsStringSync('''
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
sdks:
  dart: ">=3.8.0 <4.0.0"
''');
      expect(reader.getPatrolVersion(), isNull);
    });

    test('returns null when patrol package is missing', () {
      fs.file('/project/pubspec.lock').writeAsStringSync('''
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
  flutter:
    dependency: "direct main"
    description:
      name: flutter
      url: "https://pub.dev"
    source: hosted
    version: "3.24.0"
sdks:
  dart: ">=3.8.0 <4.0.0"
''');
      expect(reader.getPatrolVersion(), isNull);
    });

    test('returns version when patrol package exists', () {
      fs.file('/project/pubspec.lock').writeAsStringSync('''
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
  patrol:
    dependency: "direct main"
    description:
      name: patrol
      url: "https://pub.dev"
    source: hosted
    version: "3.15.0"
sdks:
  dart: ">=3.8.0 <4.0.0"
''');
      expect(reader.getPatrolVersion(), equals('3.15.0'));
    });

    test('handles dev version', () {
      fs.file('/project/pubspec.lock').writeAsStringSync('''
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
  patrol:
    dependency: "direct main"
    description:
      name: patrol
      url: "https://pub.dev"
    source: hosted
    version: "3.15.1-dev.1"
sdks:
  dart: ">=3.8.0 <4.0.0"
''');
      expect(reader.getPatrolVersion(), equals('3.15.1-dev.1'));
    });

    test('handles version with build number', () {
      fs.file('/project/pubspec.lock').writeAsStringSync('''
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
  patrol:
    dependency: "direct main"
    description:
      name: patrol
      url: "https://pub.dev"
    source: hosted
    version: "3.15.1+1"
sdks:
  dart: ">=3.8.0 <4.0.0"
''');
      expect(reader.getPatrolVersion(), equals('3.15.1+1'));
    });

    test('handles path dependency', () {
      fs.file('/project/pubspec.lock').writeAsStringSync('''
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
  patrol:
    dependency: "direct main"
    description:
      path: "../patrol"
      relative: true
    source: path
    version: "3.15.0"
sdks:
  dart: ">=3.8.0 <4.0.0"
''');
      expect(reader.getPatrolVersion(), equals('3.15.0'));
    });

    test('returns null when version field is missing', () {
      fs.file('/project/pubspec.lock').writeAsStringSync('''
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
  patrol:
    dependency: "direct main"
    description:
      name: patrol
      url: "https://pub.dev"
    source: hosted
sdks:
  dart: ">=3.8.0 <4.0.0"
''');
      expect(reader.getPatrolVersion(), isNull);
    });

    test('handles malformed yaml', () {
      fs.file('/project/pubspec.lock').writeAsStringSync('''
# Generated by pub
packages:
  patrol: invalid: yaml
''');
      expect(reader.getPatrolVersion(), isNull);
    });

    test('handles empty pubspec.lock', () {
      fs.file('/project/pubspec.lock').writeAsStringSync('');
      expect(reader.getPatrolVersion(), isNull);
    });
  });

  group('read', () {
    test('returns default config when no patrol section exists', () {
      fs.file('/project/pubspec.yaml').writeAsStringSync('''
name: test_project
dependencies:
  flutter:
    sdk: flutter
''');

      final config = reader.read();
      expect(config.testDirectory, equals('patrol_test'));
      expect(config.flutterPackageName, equals('test_project'));
    });

    test('uses custom test directory from pubspec', () {
      fs.file('/project/pubspec.yaml').writeAsStringSync('''
name: test_project
dependencies:
  flutter:
    sdk: flutter
patrol:
  test_directory: my_custom_test_dir
''');

      final config = reader.read();
      expect(config.testDirectory, equals('my_custom_test_dir'));
      expect(config.flutterPackageName, equals('test_project'));
    });

    test(
      'uses default test directory when patrol section exists but test_directory is not specified',
      () {
        fs.file('/project/pubspec.yaml').writeAsStringSync('''
name: test_project
dependencies:
  flutter:
    sdk: flutter
patrol:
  app_name: MyApp
''');

        final config = reader.read();
        expect(config.testDirectory, equals('patrol_test'));
      },
    );

    test('ignores non-string test_directory values', () {
      fs.file('/project/pubspec.yaml').writeAsStringSync('''
name: test_project
dependencies:
  flutter:
    sdk: flutter
patrol:
  test_directory: 123
''');

      final config = reader.read();
      expect(config.testDirectory, equals('patrol_test'));
    });

    test('uses default test file suffix when not specified', () {
      fs.file('/project/pubspec.yaml').writeAsStringSync('''
name: test_project
dependencies:
  flutter:
    sdk: flutter
patrol:
  app_name: MyApp
''');

      final config = reader.read();
      expect(config.testFileSuffix, equals('_test.dart'));
    });

    test('uses custom test file suffix from pubspec', () {
      fs.file('/project/pubspec.yaml').writeAsStringSync('''
name: test_project
dependencies:
  flutter:
    sdk: flutter
patrol:
  test_file_suffix: _integration_test.dart
''');

      final config = reader.read();
      expect(config.testFileSuffix, equals('_integration_test.dart'));
    });

    test('ignores non-string test_file_suffix values', () {
      fs.file('/project/pubspec.yaml').writeAsStringSync('''
name: test_project
dependencies:
  flutter:
    sdk: flutter
patrol:
  test_file_suffix: 123
''');

      final config = reader.read();
      expect(config.testFileSuffix, equals('_test.dart'));
    });

    test('handles both custom test_directory and test_file_suffix', () {
      fs.file('/project/pubspec.yaml').writeAsStringSync('''
name: test_project
dependencies:
  flutter:
    sdk: flutter
patrol:
  test_directory: custom_tests
  test_file_suffix: _patrol_test.dart
''');

      final config = reader.read();
      expect(config.testDirectory, equals('custom_tests'));
      expect(config.testFileSuffix, equals('_patrol_test.dart'));
    });
  });
}
